package com.honeybee.cloud.framework.redis.util;

import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Description redis 工具类
 * @Author DELL
 * @Create 2018-12-11
 * @Since 1.0.0
 */
@SuppressWarnings("all")
public class RedisClientTemplate {
    public final long NONE_EXPIRE = 0L;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 删除缓存<br>
     * 根据key精确匹配删除
     *
     * @param key
     */
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(Arrays.asList(key));
            }
        }
    }

    /**
     * 模糊批量删除<br>
     * （该操作会执行模糊查询，请尽量不要使用，以免影响性能或误删）
     *
     * @param pattern
     */
    public void batchDel(String... pattern) {
        for (String kp : pattern) {
            redisTemplate.delete(redisTemplate.keys(kp + "*"));
        }
    }

    /**
     * 批量查找<br>. 如果不满足，只能使用管道，根据不同的类型进行解码
     *
     * @param keys
     */
    public List multiGetObject(Collection<String> keys) {
        return redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 批量查找<br>. 如果不满足，只能使用管道，根据不同的类型进行解码
     *
     * @param keys
     */
    public List<String> multiGetString(Collection<String> keys) {
        return stringRedisTemplate.opsForValue().multiGet(keys);
    }


    /**
     * 取得缓存（字符串类型）
     *
     * @param key
     * @return 为空则返回null
     */
    public String getStr(String key) {
        return stringRedisTemplate.boundValueOps(key).get();
    }

    /**
     * 设置字符串类型值
     *
     * @param key
     * @param value
     */
    public void setStr(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    /**
     * 设置字符串类型值
     *
     * @param key
     * @param value
     * @param expireSeconds 失效时间(秒)
     */
    public void setStr(String key, String value, long expireSeconds) {
        if (expireSeconds > 0) {
            stringRedisTemplate.opsForValue().set(key, value, expireSeconds, TimeUnit.SECONDS);
        } else {
            stringRedisTemplate.opsForValue().set(key, value);
        }
    }

    /**
     * 取得缓存（int型）
     *
     * @param key
     * @return 为空则返回0
     */
    public Integer getInt(String key) {
        String value = getStr(key);
        if (org.apache.commons.lang3.StringUtils.isNumeric(value)) {
            return Integer.valueOf(value);
        }
        return null;
    }

    /**
     * 设置int类型值
     *
     * @param key
     * @param value
     */
    public void setInt(String key, int value) {
        setStr(key, Integer.toString(value));
    }

    /**
     * 设置int类型值
     *
     * @param key
     * @param value
     * @param expireSeconds 失效时间(秒)
     */
    public void setInt(String key, int value, long expireSeconds) {
        setStr(key, Integer.toString(value), expireSeconds);
    }


    /**
     * 获取Short类型值
     *
     * @param key
     * @return 为空则返回0
     */
    public Short getShort(String key) {
        String value = getStr(key);
        if (NumberUtils.isDigits(value)) {
            return Short.valueOf(value);
        }
        return null;
    }

    /**
     * 设置Short类型值
     *
     * @param key
     * @param value
     */
    public void setShort(String key, short value) {
        setStr(key, Short.toString(value));
    }

    /**
     * 设置Short类型值
     *
     * @param key
     * @param value
     * @param expireSeconds 失效时间(秒)
     */
    public void setShort(String key, short value, long expireSeconds) {
        setStr(key, Short.toString(value), expireSeconds);
    }

    /**
     * 获取Long类型值
     *
     * @param key
     * @return 为空则返回0
     */
    public Long getLong(String key) {
        String value = getStr(key);
        if (!StringUtils.isEmpty(key)) {
            return Long.valueOf(value);
        }
        return null;
    }

    /**
     * 设置Long类型值
     *
     * @param key
     * @param value
     */
    public void setLong(String key, long value) {
        setStr(key, Long.toString(value));
    }

    /**
     * 设置Long类型值
     *
     * @param key
     * @param value
     * @param expireSeconds 失效时间(秒)
     */
    public void setLong(String key, long value, long expireSeconds) {
        setStr(key, Long.toString(value), expireSeconds);
    }

    /**
     * 获取Boolean类型值
     *
     * @param key
     * @return 为空则返回null
     */
    public Boolean getBoolean(String key) {
        String value = getStr(key);
        if (!StringUtils.isEmpty(value)) {
            return Boolean.valueOf(value);
        }
        return null;
    }

    /**
     * 设置Boolean类型值
     *
     * @param key
     * @param value
     */
    public void setBoolean(String key, boolean value) {
        setStr(key, Boolean.toString(value));
    }

    /**
     * 设置Boolean类型值
     *
     * @param key
     * @param value
     * @param expireSeconds 失效时间(秒)
     */
    public void setBoolean(String key, boolean value, long expireSeconds) {
        setStr(key, Boolean.toString(value), expireSeconds);
    }

    /**
     * 获取缓存<br>
     * 注：java 8种基本类型的数据(Character除外)，请直接使用get(String key, Class<T> clazz)取值
     *
     * @param key
     * @return
     */
    public Object getObj(String key) {
        return redisTemplate.boundValueOps(key).get();
    }

    /**
     * 设置缓存<br>
     * 注：java 基本类型的数据(Character除外)，请直接使用setXXX(String key)设置值
     *
     * @param key
     * @param value
     * @return
     */
    public void setObj(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 设置缓存<br>
     * 注：java 基本类型的数据(Character除外)，请直接使用setXXX(String key)设置值
     *
     * @param key
     * @param value
     * @param expireSeconds 失效时间(秒)
     * @return
     */
    public void setObj(String key, Object value, long expireSeconds) {
        if (expireSeconds > 0) {
            redisTemplate.opsForValue().set(key, value, expireSeconds, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().set(key, value);
        }
    }

    /**
     * 获取缓存<br>
     * 注：该方法暂不支持Character数据类型
     *
     * @param key   key
     * @param clazz 类型
     * @return 为空返回null
     */
    public <T> T get(String key, Class<T> clazz) {
        if (clazz.equals(String.class)) {
            return (T) stringRedisTemplate.boundValueOps(key).get();
        }
        if (clazz.equals(Integer.class)) {
            String value = stringRedisTemplate.boundValueOps(key).get();
            if (!StringUtils.isEmpty(value)) {
                return (T) Integer.valueOf(value);
            }
            return null;
        }
        if (clazz.equals(Long.class)) {
            String value = stringRedisTemplate.boundValueOps(key).get();
            if (!StringUtils.isEmpty(value)) {
                return (T) Long.valueOf(value);
            }
            return null;
        }
        if (clazz.equals(Double.class)) {
            String value = stringRedisTemplate.boundValueOps(key).get();
            if (!StringUtils.isEmpty(value)) {
                return (T) Double.valueOf(value);
            }
            return null;
        }

        if (clazz.equals(Boolean.class)) {
            String value = stringRedisTemplate.boundValueOps(key).get();
            if (!StringUtils.isEmpty(value)) {
                return (T) Boolean.valueOf(value);
            }
            return null;
        }
        if (clazz.equals(Float.class)) {
            String value = stringRedisTemplate.boundValueOps(key).get();
            if (!StringUtils.isEmpty(value)) {
                return (T) Float.valueOf(value);
            }
            return null;
        }
        if (clazz.equals(Short.class)) {
            String value = stringRedisTemplate.boundValueOps(key).get();
            if (!StringUtils.isEmpty(value)) {
                return (T) Short.valueOf(value);
            }
            return null;
        }
        return (T) redisTemplate.boundValueOps(key).get();
    }

    /**
     * 将value对象写入缓存(不失效)
     *
     * @param key
     * @param value
     */
    public void set(String key, Object value) {
        set(key, value, NONE_EXPIRE);
    }

    /**
     * 将value对象写入缓存
     *
     * @param key
     * @param value
     * @param expireSeconds 失效时间(秒)
     */
    public void set(String key, Object value, long expireSeconds) {
        if (isBaseDataType(value.getClass())) {
            setStr(key, value.toString(), expireSeconds);
        } else {
            setObj(key, value, expireSeconds);
        }
    }

    /**
     * 判断一个类是否为基本数据类型。(只列出常用7种)
     *
     * @param clazz 要判断的类。
     */
    private boolean isBaseDataType(Class clazz) {
        return clazz.equals(String.class) ||
                clazz.equals(Integer.class) ||
                clazz.equals(Long.class) ||
                clazz.equals(Double.class) ||
                clazz.equals(Float.class) ||
                clazz.equals(Short.class) ||
                clazz.equals(Boolean.class);
    }


}
